home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
351-375
/
354
/
mxmlib
/
mxmsub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
14KB
|
634 lines
/* $Revision Header *** Header built automatically - do not edit! ***********
*
* (C) Copyright 1990 by MXM
*
* Name .....: MXMSub.c
* Created ..: Saturday 06-Jan-90 23:30
* Revision .: 5
*
* Date Author Comment
* ========= ======== ====================
* 09-Mar-90 Olsen Rework for Aztec 5.0
* 14-Jan-90 Olsen Renamed to mxm.library
* 07-Jan-90 Olsen Added InvertKeyMap
* 07-Jan-90 Olsen - Empty log message -
* 06-Jan-90 Olsen Created this file!
*
* $Revision Header ********************************************************/
#define REVISION 4
VOID
CalcDimensions(cd_String,cd_Width,cd_Height,cd_MaxWidth)
UBYTE *cd_String;
LONG *cd_Width,*cd_Height,cd_MaxWidth;
{
LONG i,cd_InLine = 0,cd_NumLines = 0;
*cd_Width = *cd_Height = 0;
for(i = 0 ; i < strlen(cd_String) ; i++)
{
if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth)
{
if(cd_InLine > *cd_Width)
*cd_Width = cd_InLine;
cd_NumLines++;
cd_InLine = 0;
continue;
}
if(cd_String[i] == '\33')
{
while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String))
i++;
if(i >= strlen(cd_String))
i = strlen(cd_String) - 1;
continue;
}
if(cd_String[i] < ' ')
continue;
cd_InLine++;
}
*cd_Height = cd_NumLines;
if(cd_InLine > *cd_Width)
*cd_Width = cd_InLine;
}
SHORT pop_computestate();
VOID pop_do_highlighting();
VOID pop_render();
VOID pop_draw_menuitem();
struct MenuItem *pop_getitem();
SHORT pop_strlen();
#define SETX 2
#define SETY 1
/*
* pop_computestate()
*
* This function checks to see where the mouse pointer is in relation to
* the various menu items in the menu. If it is inside one of them, it
* returns which one (indexed by its linear position in the MenuItem list
* with 0 being the first one). If not, returns -1.
*
* Possible future enhancement: keep a set of state variables containing
* the UL and LR corners of the last-known select box; this would make
* a quick check possible and would cut down the computation for short
* mouse movements (the most common).
*/
SHORT
pop_computestate(win, menu)
struct Window *win;
struct Menu *menu;
{
register SHORT current = 0;
register SHORT xval, yval;
register struct MenuItem *item;
/* Get the x and y vals of the mouse position */
xval = win->MouseX - SETX;
yval = win->MouseY - SETY;
/* If there is a title, decrement the yval by the correct amount */
if(menu->MenuName)
yval -= POPTITLEHEIGHT;
/* First, see if the pointer is even in the window */
if((xval < 0) || (yval < 0) ||
(xval > win->Width - SETX) || (yval > win->Height - SETY))
return(-1);
/* search through the list of menu items, checking the select box */
/* of each. If containment is detected, the job is done. */
item = menu->FirstItem;
while(item) {
if((xval >= item->LeftEdge) && (yval >= item->TopEdge) &&
(xval <= item->LeftEdge + item->Width) &&
(yval <= item->TopEdge + item->Height)) {
/* We have found the quarry; now, the result only */
/* depends on the MenuItem's ITEMENABLED flag. */
if(item->Flags & ITEMENABLED)
return(current);
else
return(-1);
}
current++;
item = item->NextItem;
}
/* If the list is exhausted, return the sad news */
return(-1);
}
/*
* pop_highlight()
*
* highlight a menu item
*/
#define pop_highlight(win, menu, state) pop_do_highlighting(win, menu, state, 0)
/*
* pop_unhighlight()
*
* unhighlight a menu item
*/
#define pop_unhighlight(win, menu, state) pop_do_highlighting(win, menu, state, 1)
/*
* pop_do_highlighting()
*
* Highlight or unhighlight a menu item, given its traversal number. Assumes
* this is a rational value -- if it isn't, Watch Out.
*/
VOID
pop_do_highlighting(win, menu, state, mode)
struct Window *win;
struct Menu *menu;
SHORT state;
SHORT mode; /* 0 means to highlight, 1 means to unhighlight */
{
register struct MenuItem *item;
struct RastPort *rp;
SHORT offset = 0;
if(menu->MenuName)
offset = POPTITLEHEIGHT;
/* Get the correct MenuItem structure */
item = pop_getitem(menu, state);
rp = win->RPort;
/* Now, do the highlighting! The action to be taken depends on */
/* the type of highlighting desired for this item. */
/* The way that the flags for highlighting works is truly bizarre */
if((item->Flags & HIGHNONE) == HIGHNONE)
return;
if(item->Flags & HIGHCOMP) {
SetDrMd(rp, COMPLEMENT);
RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
offset + SETY), (LONG) (item->LeftEdge + item->Width - 1 + SETX),
(LONG) (item->TopEdge + item->Height + offset + SETY));
}
else if(item->Flags & HIGHBOX) {
SetDrMd(rp, COMPLEMENT);
Move(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
offset + SETY));
Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX),
(LONG) (item->TopEdge + offset + SETY));
Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX),
(LONG) (item->TopEdge + item->Height + offset + SETY));
Move(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX),
(LONG) (item->TopEdge + offset + 1 + SETY));
Draw(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX),
(LONG) (item->TopEdge + item->Height + offset + SETY));
Draw(rp, (LONG) item->LeftEdge + SETX,
(LONG) (item->TopEdge + item->Height + offset + SETY));
Draw(rp, (LONG) item->LeftEdge + SETX, (LONG)
(item->TopEdge + offset + 1 + SETY));
Move(rp, (LONG) item->LeftEdge + 1 + SETX, (LONG)
(item->TopEdge + offset + 1 + SETY));
Draw(rp, (LONG) item->LeftEdge + 1 + SETX,
(LONG) (item->TopEdge + item->Height + offset - 1 + SETY));
}
/* Otherwise, the mode is HIGHIMAGE */
else
pop_draw_menuitem(win, item, !mode, offset);
}
/*
* pop_render()
*
* renders the menu title (if existent) and the menu items
*/
VOID
pop_render(win, menu)
struct Window *win;
struct Menu *menu;
{
struct MenuItem *item;
struct RastPort *rp;
SHORT offset = 0;
rp = win->RPort;
/* Fill the background with color 1, like Intuition Menus */
SetAPen(rp, 1L);
RectFill(rp, 0L + SETX, 0L + SETY, (LONG) win->Width - SETX - 1, (LONG) win->Height - 2 - SETY);
/* First, if there is a Title for this menu, render it in the top */
/* of the menu. */
if(menu->MenuName) {
SetDrMd(rp, JAM1);
SetAPen(rp, 1L);
RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1);
SetAPen(rp, 0L);
SetBPen(rp, 1L);
Move(rp, 4L + SETX, 7L);
Text(rp, menu->MenuName, (LONG) pop_strlen(menu->MenuName));
SetDrMd(rp, COMPLEMENT);
RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1);
SetDrMd(rp, JAM1);
offset = POPTITLEHEIGHT;
SetAPen(rp, 0);
Move(rp, 0, POPTITLEHEIGHT);
Draw(rp, win->Width - 1, POPTITLEHEIGHT);
}
/* now render all of the menu items */
item = menu->FirstItem;
while(item) {
pop_draw_menuitem(win, item, 0, offset);
item = item->NextItem;
}
}
/*
* pop_draw_menuitem()
*
* Draws the specified menuitem in the given rastport. The mode argument
* says what to draw -- 0 means draw the ItemFill, 1 the SelectFill.
*/
VOID
pop_draw_menuitem(win, item, mode, offset)
struct Window *win;
struct MenuItem *item;
SHORT mode;
SHORT offset;
{
/* Area fill patterns */
static USHORT pop_ghost_pattern[] = {
0x1111, 0x4444
};
static USHORT pop_normal_pattern[] = {
0xffff, 0xffff
};
APTR fill;
struct RastPort *rp;
/* first, figure out what to do, and return if it is a NULL thing */
if(!mode)
fill = item->ItemFill;
else
fill = item->SelectFill;
if(!fill)
return;
rp = win->RPort;
/* First, erase what may already be there, just to be sure that */
/* everything works out all right. */
SetAPen(rp, 1L);
SetDrMd(rp, JAM1);
RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG)
(item->TopEdge + item->Height + offset + SETY));
/* If the item is checkmarked, draw the checkmark. Intuition made */
/* sure that the CheckMark field of the window structure exists */
if(item->Flags & CHECKIT)
if(item->Flags & CHECKED)
DrawImage(rp, win->CheckMark, (LONG) item->LeftEdge + SETX,
(LONG) (item->TopEdge + offset + 1 + SETY));
/* Now, draw the item itself -- depending on the Flag value, it */
/* could be either an Image or an IntuiText */
if(item->Flags & ITEMTEXT)
PrintIText(rp, fill, (LONG) item->LeftEdge + SETX,
(LONG) (item->TopEdge + offset + SETY));
else
DrawImage(rp, fill, (LONG) item->LeftEdge + SETX,
(LONG) (item->TopEdge + offset + SETY));
/* If the ITEMENABLED flag is not set, "ghost" the item. */
if(!(item->Flags & ITEMENABLED)) {
SetAPen(rp, 1L);
SetDrMd(rp, JAM1);
SetAfPt(rp, (USHORT *) pop_ghost_pattern, 1L);
RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG)
(item->TopEdge + item->Height + offset + SETY));
SetAfPt(rp, (USHORT *) pop_normal_pattern, 1L);
}
}
/*
* pop_getitem()
*
* given the traversal number of a menu item in a menu (assumes, BTW, that
* the arguments are valid), return a pointer to the MenuItem structure
*/
struct MenuItem *
pop_getitem(menu, which)
struct Menu *menu;
SHORT which;
{
struct MenuItem *item;
item = menu->FirstItem;
while(which--)
item = item->NextItem;
return(item);
}
/*
* pop_strlen()
*
* a home-brewed strlen to prevent it being necessary to hook in whatever
* huge object file in which the c library's strlen() resides.
*/
SHORT
pop_strlen(str)
char *str;
{
register SHORT count = 0;
for(; *str++; count++);
return(count);
}
#define CONTROLBITS ( (1 << 5) | (1 << 6) )
ULONG
InvertKeyMap(ansicode,ie,km)
ULONG ansicode;
register struct InputEvent *ie;
struct KeyMap *km;
{
LONG kindex;
UBYTE code = 0;
ie -> ie_Class = IECLASS_RAWKEY;
ie -> ie_EventAddress = 0;
/* check for codes in (default) high map first */
switch(ansicode)
{
case ' ': code = 0x40; /* space */
break;
case 0x08: code = 0x41; /* backspace */
break;
case '\t': code = 0x42; /* tab */
break;
case 0x0D: code = 0x44; /* return */
break;
case 0x1B: code = 0x45; /* esc */
break;
case 0x7F: code = 0x46; /* del */
break;
}
ie -> ie_Code = 0;
ie -> ie_Qualifier = 0;
if(code)
{
ie -> ie_Code = code;
ie -> ie_Qualifier = 0;
return(TRUE);
}
LowKeyInvert((UBYTE)ansicode,km,&ie -> ie_Code,&ie -> ie_Qualifier,&kindex);
if(!ie -> ie_Code && !ie -> ie_Qualifier)
return(FALSE);
return(TRUE);
}
#define KEYMAPSIZE 64
/* LowKeyInvert returns good code else <0 if no find
*
* regarding keymap as many-to-one mapping:
* -entries for a given key are scanned so that
* the minimum number of qualifiers are associated
* with the keystroke.
* -passing a character value of zero corresponds, in
* the default keymap, to CTRL-`, which is probably a bug.
* -numerals are matched with numeric pad keystrokes (no
* qualifiers) on standard keymap. The way to specify
* a key on the number row is via its shifted value;
* specify explicitly that the qualifier is to be unshifted,
* or a "don't care."
*/
LowKeyInvert(value,km,codep,qualp,indexp)
register UBYTE value; /* translation value from low keymap */
struct KeyMap *km;
UWORD *codep; /* pointers where answers are to be put */
UWORD *qualp;
ULONG *indexp; /* dead-key index information (put into ie?) */
{
register UWORD code = KEYMAPSIZE - 1; /* last entry */
register unsigned int type;
register LONG *p; /* points to four-byte lokeymap entry */
int found_it = 0;
*indexp = *qualp = 0;
p = (LONG *)km -> km_LoKeyMap + code;
do
{
/* determine type of key */
if((type = km -> km_LoKeyMapTypes[code]) == KC_VANILLA)
found_it = CheckVanilla(p,value,qualp);
else
if(!(type & KCF_NOP))
found_it = CheckNormal(p,value,type,qualp);
--p;
}
while(!found_it && code--);
*codep = code;
return(code);
}
CheckNormal(four_bytesp, val, type, qualp)
LONG four_bytesp;
UBYTE val;
UWORD type;
UWORD *qualp;
{
register UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word */
register long position;
/* start with last of four bytes, "more vanilla" */
p += 3;
for(position = 3 ; position >= 0 ; --position, --p)
{
if(*p == val)
{
switch(type)
{
case KC_NOQUAL: if(position != 3)
goto NOT_THIS;
break;
case KCF_SHIFT: if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_LSHIFT;
break;
case KCF_ALT: if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_LALT;
break;
case KCF_CONTROL:
if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_ALT | KCF_CONTROL:
if(!(position & 1))
*qualp |= IEQUALIFIER_LALT;
if(!(position & 2))
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_SHIFT | KCF_CONTROL:
if(!(position & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(position & 2))
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_SHIFT | KCF_ALT:
if(!(position & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(position & 2))
*qualp |= IEQUALIFIER_LALT;
break;
default: break;
}
return(TRUE);
}
NOT_THIS: ;
}
return(FALSE);
}
CheckVanilla(p,val,qualp)
UBYTE *p; /* note: byte pointer */
UBYTE val;
UWORD *qualp;
{
register int i;
/* only one way to match a vanilla control key */
if(!(val & CONTROLBITS))
{
/* is a control code */
if((p[3] & ~CONTROLBITS) == val)
{
*qualp |= IEQUALIFIER_CONTROL;
return(TRUE);
}
}
else
{
/* not a control */
for(i = 3 ; i >= 0 ; --i)
{
if(p[i] == val)
{
if(!(i & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(i & 2))
*qualp |= IEQUALIFIER_LALT;
return(TRUE);
}
}
}
return(FALSE);
}